/**
 * 路由守卫组件
 * 用于保护需要认证或特定权限的路由
 */
import React from 'react';
import { Navigate, useLocation } from 'react-router-dom';
import { Result, Button, Spin } from 'antd';
import { LockOutlined, UserOutlined } from '@ant-design/icons';
import { useAuth } from '../contexts/AuthContext';
import { RouteGuard } from '../types/auth';

interface ProtectedRouteProps extends RouteGuard {
  children: React.ReactNode;
  fallback?: React.ReactNode;
}

const ProtectedRoute: React.FC<ProtectedRouteProps> = ({
  children,
  permissions = [],
  roles = [],
  requireAuth = true,
  requireAll = false,
  fallback
}) => {
  const { state, hasPermission, hasRole, hasAnyPermission, hasAllPermissions, hasAnyRole } = useAuth();
  const location = useLocation();

  // 如果正在加载认证状态，显示加载器
  if (state.loading) {
    return (
      <div style={{ 
        display: 'flex', 
        justifyContent: 'center', 
        alignItems: 'center', 
        height: '100vh' 
      }}>
        <Spin size="large" tip="正在验证身份..." />
      </div>
    );
  }

  // 如果需要认证但用户未登录，重定向到登录页
  if (requireAuth && !state.isAuthenticated) {
    return <Navigate to="/login" state={{ from: location }} replace />;
  }

  // 如果不需要认证，直接渲染子组件
  if (!requireAuth) {
    return <>{children}</>;
  }

  // 检查权限
  if (permissions.length > 0) {
    const hasRequiredPermissions = requireAll 
      ? hasAllPermissions(permissions)
      : hasAnyPermission(permissions);

    if (!hasRequiredPermissions) {
      if (fallback) {
        return <>{fallback}</>;
      }

      return (
        <Result
          status="403"
          title="权限不足"
          subTitle={`您没有访问此页面的权限。需要权限: ${permissions.join(', ')}`}
          icon={<LockOutlined />}
          extra={
            <Button type="primary" onClick={() => window.history.back()}>
              返回上一页
            </Button>
          }
        />
      );
    }
  }

  // 检查角色
  if (roles.length > 0) {
    const hasRequiredRoles = requireAll 
      ? roles.every(role => hasRole(role))
      : hasAnyRole(roles);

    if (!hasRequiredRoles) {
      if (fallback) {
        return <>{fallback}</>;
      }

      return (
        <Result
          status="403"
          title="角色权限不足"
          subTitle={`您的角色无法访问此页面。需要角色: ${roles.join(', ')}`}
          icon={<UserOutlined />}
          extra={
            <Button type="primary" onClick={() => window.history.back()}>
              返回上一页
            </Button>
          }
        />
      );
    }
  }

  // 所有检查通过，渲染子组件
  return <>{children}</>;
};

export default ProtectedRoute;

// 便捷的权限检查组件
export const RequirePermission: React.FC<{
  permission: string;
  children: React.ReactNode;
  fallback?: React.ReactNode;
}> = ({ permission, children, fallback = null }) => {
  return (
    <ProtectedRoute 
      permissions={[permission]} 
      fallback={fallback}
    >
      {children}
    </ProtectedRoute>
  );
};

// 便捷的角色检查组件
export const RequireRole: React.FC<{
  role: string;
  children: React.ReactNode;
  fallback?: React.ReactNode;
}> = ({ role, children, fallback = null }) => {
  return (
    <ProtectedRoute 
      roles={[role]} 
      fallback={fallback}
    >
      {children}
    </ProtectedRoute>
  );
};

// 便捷的多权限检查组件
export const RequireAnyPermission: React.FC<{
  permissions: string[];
  children: React.ReactNode;
  fallback?: React.ReactNode;
}> = ({ permissions, children, fallback = null }) => {
  return (
    <ProtectedRoute 
      permissions={permissions} 
      requireAll={false}
      fallback={fallback}
    >
      {children}
    </ProtectedRoute>
  );
};

// 便捷的多权限检查组件（需要全部权限）
export const RequireAllPermissions: React.FC<{
  permissions: string[];
  children: React.ReactNode;
  fallback?: React.ReactNode;
}> = ({ permissions, children, fallback = null }) => {
  return (
    <ProtectedRoute 
      permissions={permissions} 
      requireAll={true}
      fallback={fallback}
    >
      {children}
    </ProtectedRoute>
  );
};

// 便捷的多角色检查组件
export const RequireAnyRole: React.FC<{
  roles: string[];
  children: React.ReactNode;
  fallback?: React.ReactNode;
}> = ({ roles, children, fallback = null }) => {
  return (
    <ProtectedRoute 
      roles={roles} 
      requireAll={false}
      fallback={fallback}
    >
      {children}
    </ProtectedRoute>
  );
};

// 管理员专用组件
export const AdminOnly: React.FC<{
  children: React.ReactNode;
  fallback?: React.ReactNode;
}> = ({ children, fallback = null }) => {
  return (
    <RequireRole role="admin" fallback={fallback}>
      {children}
    </RequireRole>
  );
};

// 条件渲染组件（基于权限）
export const ConditionalRender: React.FC<{
  condition: 'permission' | 'role' | 'authenticated';
  value?: string | string[];
  requireAll?: boolean;
  children: React.ReactNode;
  fallback?: React.ReactNode;
}> = ({ condition, value, requireAll = false, children, fallback = null }) => {
  const { state, hasPermission, hasRole, hasAnyPermission, hasAllPermissions, hasAnyRole } = useAuth();

  let shouldRender = false;

  switch (condition) {
    case 'authenticated':
      shouldRender = state.isAuthenticated;
      break;
    
    case 'permission':
      if (typeof value === 'string') {
        shouldRender = hasPermission(value);
      } else if (Array.isArray(value)) {
        shouldRender = requireAll 
          ? hasAllPermissions(value)
          : hasAnyPermission(value);
      }
      break;
    
    case 'role':
      if (typeof value === 'string') {
        shouldRender = hasRole(value);
      } else if (Array.isArray(value)) {
        shouldRender = requireAll 
          ? value.every(role => hasRole(role))
          : hasAnyRole(value);
      }
      break;
    
    default:
      shouldRender = false;
  }

  return shouldRender ? <>{children}</> : <>{fallback}</>;
};

// Hook for permission checking
export const usePermissionCheck = () => {
  const { hasPermission, hasRole, hasAnyPermission, hasAllPermissions, hasAnyRole } = useAuth();

  return {
    hasPermission,
    hasRole,
    hasAnyPermission,
    hasAllPermissions,
    hasAnyRole,
    checkPermission: (permission: string) => hasPermission(permission),
    checkRole: (role: string) => hasRole(role),
    checkAnyPermission: (permissions: string[]) => hasAnyPermission(permissions),
    checkAllPermissions: (permissions: string[]) => hasAllPermissions(permissions),
    checkAnyRole: (roles: string[]) => hasAnyRole(roles),
  };
};
